home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 3: CDPD 3
/
Almathera Ten on Ten - Disc 3: CDPD3.iso
/
fish
/
001-100
/
001-025
/
018
/
scrimper
/
scrimper.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-17
|
13KB
|
542 lines
#include <exec/types.h>
#include <exec/memory.h>
#include <intuition/intuition.h>
/*
** S C R E E N I M A G E P R I N T E R (SCRIMPER)
**
** Copyright 1986 By Perry S. Kivolowitz
**
** The author grants permission to duplicate and reproduce
** this software provided that no commercial gain can be
** had as a consequence of use or reproduction of this
** software and that this and other identifying informat-
** be left intact.
**
** This software is provided as a service to the readers
** of Amazing Computing and does not imply any commitment
** on behalf of the author to provide support nor can the
** author be held liable for the consequences of use or
** misuse of this software.
**
*/
/*
** Overview
**
** This program dynamically builds a list of screens each time its
** title bar is selected (note that the window this program creates
** is only as large as its title bar). The list of screens is dis-
** played when the right mouse button is depressed (and sometimes
** when it's just feeling lonely too). Select a screen as you would
** select an item from a menu.
**
** Something to note is the way the screen selection menu centers
** each item. This is done by the routine ``massage_left_edges.''
**
** After a screen has been selected, the screen selection menu is
** replaced with a function selection menu. There are currently
** three things which scrimper allows you to do:
**
** (1) Bring the selected screen to front.
**
** This is kind of neat especially when you have many
** screens open at once. This gives you a sort of direct
** access capability instead of many repititions of ``screen
** to front.''
**
** When the selected screen comes to the front if you push
** the left mouse button, the current front most screen be-
** comes the actual front screen.
**
** If you click the right mouse button, the screen SCRIMPER
** was run from will come back to the front. This is very
** useful for quickly checking the status of program running
** on another screen and whipping back to the original
** screen.
**
** (2) The selected screen can be printed.
**
** The selected screen will be brought to the front for half
** a second (literally) just for you to make sure you sel-
** ected the right screen. Then the screen SCRIMPER was run
** from comes back to the front and a requester asks if you
** really want to print the screen.
**
** If yes, SCRIMPER will try to create a copy of the screen
** in its own dynamically allocated memory. If it can, you
** are free to modify or even delete the screen without af-
** fecting the printout. If SCRIMPER can't allocate enough
** CHIP memory, it will ask you (with a requester) if you
** still want to print the screen even though SCRIMPER will
** have to use the *LIVE* copy. If that's ok, unpredictable
** results will occur if you modify or delete the screen
** while SCRIMPER is printing.
**
** What's neat here is that you can print any screen. Even
** if your program has no screen dump capability. If it does
** (for example, DPaint) SCRIMPER is *still very useful*
** since it will baby sit the printer rather than forcing
** (for example) DPaint to do so.
**
** (3) Go Back To Screen Select
**
** This is the way to tell SCRIMPER to forget that you
** selected a screen.
**
** Known Bugs:
**
** (1) Assumes 640 wide screen.
**
** (2) If printer trouble arises and the user aborts by cancelling
** the print out from the System Requester, AmigaDos loses 2K
** of memory and sometimes tosses its cookies.
**
**
** Suggested Improvements
**
** (1) Allow variable density printing. The printer driver sup-
** ports this directly. Very neat C-A!
**
** (2) Allow sections of a screen to be printed. IE: allow user
** to sweep out a box over a screen and print only what's
** inside.
**
** (3) Adjust for 320 wide screen dynamically.
**
** Compilation Information
**
** This code was developed using Manx C Beta 1.99E, 1.99F, and Manx
** C 3.20A (a final release).
**
** Defining PRINTF causes printf's to be loaded which increases the
** size of the executable to 9160 from 6520 bytes (approximately).
** By not defining PRINTF you can be confident of SCRIMPER working
** from the WORKBENCH.
**
** Link with printer.o
**
**
** STRONG SUGGESTION: Avoid burning out your print head and ribbon
** by making the background color of the screen
** white - I did and got used to it.
*/
#define WWIDTH 640
#define MAX_SCREENS 20
#define SIZE_MI (sizeof(struct MenuItem))
#define SIZE_IT (sizeof(struct IntuiText))
extern void *OpenLibrary();
extern void *GetMsg();
extern void *OpenWindow();
extern void *ItemAddress();
int is_cli = 0;
int which_screen = 0;
char *window_title = "SCReen IMage PrintER V0.6 (PSKivolowitz)";
extern char *calloc();
struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct Window *w;
struct Screen *s[MAX_SCREENS];
char *stitles[MAX_SCREENS];
struct IntuiMessage *message;
int screen_count = 0;
extern generic_cleanup();
extern screen_init() , screen_pick();
extern func_init() , func_pick();
struct IntuiText print_scrn_it = {
0 , 1 , JAM2 , 0 , 0 , NULL , (UBYTE *) "print selected screen" , NULL
};
struct IntuiText back_2_scrn_it = {
0 , 1 , JAM2 , 0 , 0 , NULL , (UBYTE *) "return to screen selection" , NULL
};
struct IntuiText scrn_2_frnt_it = {
0 , 1 , JAM2 , 0 , 0 , NULL , (UBYTE *) "selected screen to front" , NULL
};
struct MenuItem back_to_screen_select = {
NULL , -5 , 22 , 0 , 11 ,
ITEMTEXT | ITEMENABLED | HIGHCOMP ,
0 , (APTR) &back_2_scrn_it , NULL , NULL , NULL
};
struct MenuItem print_screen = {
&back_to_screen_select , -5 , 11 , 0 , 11 ,
ITEMENABLED | ITEMTEXT | HIGHCOMP ,
0 , (APTR) &print_scrn_it , NULL , NULL , NULL
};
struct MenuItem screen_to_front = {
&print_screen , -5 , 0 , 0 , 11 ,
ITEMTEXT | ITEMENABLED | HIGHCOMP ,
0 , (APTR) &scrn_2_frnt_it , NULL , NULL , NULL
};
struct Menu function_menu = {
NULL ,
10 , 0 , 130 , 10 ,
MENUENABLED ,
"Select Function" ,
&screen_to_front
};
struct Menu screen_menu = {
NULL ,
10 , 0 , 120 , 10 ,
MENUENABLED ,
"Select Screen" ,
NULL
};
struct jmptbl {
struct Menu *menu;
int (*init)();
int (*cleanup)();
int (*pick)();
};
struct jmptbl scrn_jmptbl = {
&screen_menu ,
screen_init ,
generic_cleanup ,
screen_pick
};
struct jmptbl func_jmptbl = {
&function_menu ,
func_init ,
generic_cleanup ,
func_pick
};
struct NewWindow nw = {
0,10,
WWIDTH,10,
-1,-1,
ACTIVEWINDOW | INACTIVEWINDOW | CLOSEWINDOW | MENUPICK ,
WINDOWDEPTH | WINDOWDRAG | NOCAREREFRESH | WINDOWCLOSE ,
NULL,NULL,
NULL ,
NULL,NULL,0,0,0,0,WBENCHSCREEN
};
#define IBPtr struct IntuitionBase *
alloc_menu_item(p , i , s)
register struct MenuItem **p;
register char *s;
{
*p = (struct MenuItem *) calloc(1 , SIZE_MI);
if (*p) {
(*p)->NextItem = NULL;
(*p)->Height = w->WScreen->Font->ta_YSize;
(*p)->TopEdge = i * (*p)->Height;
(*p)->LeftEdge = -5;
(*p)->Flags = ITEMTEXT | ITEMENABLED | HIGHCOMP;
(*p)->Command = NULL;
(*p)->SubItem = NULL;
(*p)->NextSelect = NULL;
(*p)->MutualExclude = (long) ~(1 << i);
alloc_intuitext(&((*p)->ItemFill) , s);
if (!(*p)->ItemFill) *p = NULL;
else (*p)->Width = IntuiTextLength((*p)->ItemFill);
}
}
alloc_intuitext(p , s)
register struct IntuiText **p;
register char *s;
{
register char *d = NULL;
register int length = strlen(s) + 1;
if (length & 1) length++;
*p = (struct IntuiText *) calloc(1 , SIZE_IT);
if (*p) {
d = calloc(1 , length);
if (d) {
(*p)->FrontPen = 0;
(*p)->BackPen = 1;
(*p)->LeftEdge = 0;
(*p)->TopEdge = 0;
(*p)->DrawMode = JAM2;
(*p)->ITextFont = NULL;
(*p)->NextText = NULL;
(*p)->IText = (UBYTE *) d;
strcpy(d , s);
} else *p = NULL;
}
}
#define EVEN(S) ((S) & 1 ? (S) + 1 : (S))
get_screens()
{
register int i = 0;
Forbid();
s[0] = w->WScreen;
stitles[0] = calloc(1 , EVEN(strlen(s[0]->Title)+1));
screen_count = 1;
if (stitles[0]) {
strcpy(stitles[0] , s[0]->Title);
while (s[i++]->NextScreen) {
s[i] = s[i-1]->NextScreen;
stitles[i] = calloc(1 , EVEN(strlen(s[i]->Title)+1));
if (stitles[i]) strcpy(stitles[i] , s[i]->Title);
else {
Permit();
return((int) FALSE);
}
screen_count++;
}
}
Permit();
return((int) TRUE);
}
build_menu(menu , scrn)
register struct Menu *menu;
register struct Screen *scrn;
{
register int i;
register struct MenuItem *p;
if (get_screens()) {
alloc_menu_item(&menu->FirstItem , 0 , stitles[0]);
if (!menu->FirstItem) return((int) FALSE);
p = menu->FirstItem;
for (i = 1; i < screen_count; i++) {
alloc_menu_item(&(p->NextItem) , i , stitles[i]);
if (!p->NextItem) return((int) FALSE);
p = p->NextItem;
}
return((int) TRUE);
}
return((int) FALSE);
}
main()
{
extern void massage_left_edges();
is_cli = 1;
IntuitionBase = (IBPtr) OpenLibrary("intuition.library" , 0L);
if (!IntuitionBase) {
#ifdef PRINTF
if (is_cli) printf("could not open intuition library\n");
#endif
exit(1);
}
GfxBase = (struct GfxBase *) OpenLibrary("graphics.library" , 0L);
if (!GfxBase) {
#ifdef PRINTF
if (is_cli) printf("could not open graphics library\n");
#endif
CloseLibrary(IntuitionBase);
exit(1);
}
if (! (w = (struct Window *) OpenWindow(&nw))) {
#ifdef PRINTF
if (is_cli) printf("could not open dummy window\n");
#endif
CloseLibrary(GfxBase);
CloseLibrary(IntuitionBase);
exit(1);
}
SetWindowTitles(w , window_title , -1L);
set_widths(&function_menu);
massage_left_edges(&function_menu);
while (message = (struct IntuiMessage *) GetMsg(w->UserPort)) ReplyMsg(message);
while (getmenu(&scrn_jmptbl)) ;
out: while (message = (struct IntuiMessage *) GetMsg(w->UserPort)) ReplyMsg(message);
SetWindowTitles(w , NULL , NULL);
CloseWindow(w);
CloseLibrary(GfxBase);
CloseLibrary(IntuitionBase);
exit(0);
}
screen_pick(code)
USHORT code;
{
which_screen = ITEMNUM(code);
return(getmenu(&func_jmptbl));
}
freeall()
{
register int i;
register struct MenuItem *p = screen_menu.FirstItem;
register struct IntuiText *t;
register struct MenuItem *pnext;
for (i = 0; i < screen_count; i++) if (stitles[i]) free(stitles[i]);
while (p) {
if (p->ItemFill) {
t = (struct IntuiText *) p->ItemFill;
if (t) {
if (t->IText) free(t->IText);
free(t);
}
}
pnext = p->NextItem;
free(p);
p = pnext;
}
screen_menu.FirstItem = NULL;
screen_count = 0;
}
void massage_left_edges(menu)
register struct Menu *menu;
{
register int max_width = 0;
register struct MenuItem *p = menu->FirstItem;
if (!p) return;
while (p) {
if (p->Width > max_width) max_width = p->Width;
p = p->NextItem;
}
p = menu->FirstItem;
while (p) {
((struct IntuiText *) (p->ItemFill))->LeftEdge = (max_width - p->Width) / 2;
p->Width = max_width;
p = p->NextItem;
}
}
set_widths(menu)
register struct Menu *menu;
{
register struct MenuItem *p = menu->FirstItem;
while (p) {
p->Width = IntuiTextLength(p->ItemFill);
p = p->NextItem;
}
}
func_pick(code)
USHORT code;
{
register struct Screen *scrn;
extern struct Screen *verify_screen_pointer();
register ULONG class;
if (scrn = verify_screen_pointer())
switch (ITEMNUM(code)) {
case 2: return((int) TRUE);
case 1: ClearMenuStrip(w);
dump_screen(scrn,0,0,scrn->Width,scrn->Height);
return((int) TRUE);
case 0: if (scrn == w->WScreen) break;
ScreenToFront(scrn);
Wait(1L << w->UserPort->mp_SigBit);
message = (struct IntuiMessage *) GetMsg(w->UserPort);
if (message) {
class = message->Class;
ReplyMsg(message);
if (class != INACTIVEWINDOW) ScreenToFront(w->WScreen);
if (class == CLOSEWINDOW) return((int) FALSE);
}
return((int) TRUE);
}
DisplayBeep(w->WScreen);
return((int) TRUE);
}
struct Screen *verify_screen_pointer()
{
register struct Screen *hoped_for;
register struct Screen *p;
if (! (hoped_for = s[which_screen])) return(NULL);
p = s[0];
while (p) {
if (p == hoped_for) return(hoped_for);
p = p->NextScreen;
}
return(NULL);
}
func_init()
{
ClearMenuStrip(w);
SetMenuStrip(w , &function_menu);
return((int) TRUE);
}
generic_cleanup()
{
ClearMenuStrip(w);
freeall();
}
screen_init()
{
if (!build_menu(&screen_menu , NULL)) return((int) FALSE);
massage_left_edges(&screen_menu);
SetMenuStrip(w , &screen_menu);
return((int) TRUE);
}
getmenu(jmptbl)
register struct jmptbl *jmptbl;
{
register struct MenuItem *mi;
register ULONG class;
register USHORT code , code_save;
register int ret_val;
if (! (*jmptbl->init)()) return((int) FALSE);
while (1) {
message = (struct IntuiMessage *) GetMsg(w->UserPort);
if (!message) {
Wait(1L << w->UserPort->mp_SigBit);
continue;
}
class = message->Class;
code = message->Code;
ReplyMsg(message);
switch (class) {
case CLOSEWINDOW:
(*jmptbl->cleanup)();
return((int) FALSE);
case INACTIVEWINDOW:
case ACTIVEWINDOW:
(*jmptbl->cleanup)();
return((int) TRUE);
case MENUPICK:
if (code == MENUNULL) continue;
while (code != MENUNULL) {
mi = (struct MenuItem *) ItemAddress(jmptbl->menu , (long) code);
code_save = code;
code = mi->NextSelect;
}
ret_val = (*jmptbl->pick)(code_save);
(*jmptbl->cleanup)();
return(ret_val);
}
}
}